package com.example.rabbitmq.starter.autoconfigure;

import com.example.rabbitmq.starter.config.DynamicRabbitMQConfig;
import com.example.rabbitmq.starter.config.JacksonConfig;
import com.example.rabbitmq.starter.config.RabbitListenerConfig;
import com.example.rabbitmq.starter.config.RabbitMQConfig;
import com.example.rabbitmq.starter.config.RabbitMQProperties;
import com.example.rabbitmq.starter.handler.FailureHandlerFactory;
import com.example.rabbitmq.starter.producer.MessageProducerFactory;
import com.example.rabbitmq.starter.service.FailedMessageService;
import com.example.rabbitmq.starter.service.MQConfigService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.boot.autoconfigure.domain.EntityScan;

/**
 * RabbitMQ自动配置类
 */
@Configuration
@ConditionalOnClass(name = "org.springframework.amqp.rabbit.core.RabbitTemplate")
@AutoConfigureAfter(RabbitAutoConfiguration.class)
@EnableConfigurationProperties(RabbitMQProperties.class)
@ConditionalOnProperty(prefix = "rabbitmq.starter", name = "enabled", havingValue = "true", matchIfMissing = true)
@Import({
    RabbitMQConfig.class,
    JacksonConfig.class,
    RabbitListenerConfig.class,
    DynamicRabbitMQConfig.class
})
@EnableJpaRepositories(basePackages = "com.example.rabbitmq.starter")
@EntityScan(basePackages = "com.example.rabbitmq.starter")
@ComponentScan(basePackages = {"com.example.rabbitmq.starter"})
public class RabbitMQAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public MessageProducerFactory messageProducerFactory(RabbitTemplate rabbitTemplate, ObjectMapper objectMapper, MQConfigService mqConfigService) {
        return new MessageProducerFactory(rabbitTemplate, objectMapper, mqConfigService);
    }

    @Bean
    @ConditionalOnMissingBean
    public FailureHandlerFactory failureHandlerFactory(ApplicationContext applicationContext) {
        return new FailureHandlerFactory(applicationContext);
    }

    @Bean
    @ConditionalOnMissingBean
    public MQConfigService mqConfigService(com.example.rabbitmq.starter.dao.MQConfigRepository mqConfigRepository, RabbitAdmin rabbitAdmin) {
        return new MQConfigService(mqConfigRepository, rabbitAdmin);
    }

    @Bean
    @ConditionalOnMissingBean
    public FailedMessageService failedMessageService(com.example.rabbitmq.starter.dao.FailedMessageRepository failedMessageRepository, RabbitTemplate rabbitTemplate, RabbitAdmin rabbitAdmin, ObjectMapper objectMapper, MQConfigService mqConfigService, FailureHandlerFactory failureHandlerFactory) {
        return new FailedMessageService(failedMessageRepository, rabbitTemplate, rabbitAdmin, objectMapper, mqConfigService, failureHandlerFactory);
    }
}